#include <cstdlib>
#include <qgroupbox.h>
#include <qcombobox.h>
#include <qlayout.h>
#include <qstatusbar.h>
#include <qlabel.h>
#include <qwt_plot.h>
#include <qwt_plot_rescaler.h>
#include <qwt_scale_div.h>
#include "plot.h"
#include "mainwindow.h"

MainWindow::MainWindow()
{
    QFrame *w = new QFrame(this);

    QWidget *panel = createPanel(w);
    panel->setFixedWidth(2 * panel->sizeHint().width());
    d_plot = createPlot(w);

    QHBoxLayout *layout = new QHBoxLayout(w);
    layout->setMargin(0);
    layout->addWidget(panel, 0);
    layout->addWidget(d_plot, 10);

    setCentralWidget(w);

    setRescaleMode(0);
    setMouseMode(0);

    (void)statusBar();
}

QWidget *MainWindow::createPanel(QWidget *parent)
{
    QGroupBox *panel = new QGroupBox("Navigation Panel", parent);

    QComboBox *navigationBox = new QComboBox(panel);
    navigationBox->setEditable(false);
#if QT_VERSION < 0x040000
    navigationBox->insertItem("Tracking", Tracking);
    navigationBox->insertItem("Zooming", Zooming);
    navigationBox->insertItem("Panning", Panning);
#else
    navigationBox->insertItem(Tracking, "Tracking");
    navigationBox->insertItem(Zooming, "Zooming");
    navigationBox->insertItem(Panning, "Panning");
#endif
    connect(navigationBox, SIGNAL(activated(int)), SLOT(setMouseMode(int)));

    d_navigationInfo = new QLabel(panel);
    d_navigationInfo->setSizePolicy(
        QSizePolicy::Expanding, QSizePolicy::Expanding); 
#if QT_VERSION >= 0x040000
    d_navigationInfo->setWordWrap(true);
#endif

    QComboBox *rescaleBox = new QComboBox(panel);
    rescaleBox->setEditable(false);
#if QT_VERSION < 0x040000
    rescaleBox->insertItem("None", KeepScales);
    rescaleBox->insertItem("Fixed", Fixed);
    rescaleBox->insertItem("Expanding", Expanding);
    rescaleBox->insertItem("Fitting", Fitting);
#else
    rescaleBox->insertItem(KeepScales, "None");
    rescaleBox->insertItem(Fixed, "Fixed");
    rescaleBox->insertItem(Expanding, "Expanding");
    rescaleBox->insertItem(Fitting, "Fitting");
#endif
    connect(rescaleBox, SIGNAL(activated(int)), SLOT(setRescaleMode(int)));

    d_rescaleInfo = new QLabel(panel);
    d_rescaleInfo->setSizePolicy(
        QSizePolicy::Expanding, QSizePolicy::Expanding); 
#if QT_VERSION >= 0x040000
    d_rescaleInfo->setWordWrap(true);
#endif

    QVBoxLayout *layout = new QVBoxLayout(panel);
    layout->addWidget(navigationBox);
    layout->addWidget(d_navigationInfo);
    layout->addWidget(rescaleBox);
    layout->addWidget(d_rescaleInfo);
    layout->addStretch(10);

    return panel;
}

Plot *MainWindow::createPlot(QWidget *parent)
{
    Plot *plot = new Plot(parent, QwtDoubleInterval(0.0, 1000.0));
    plot->replot();

    d_rescaler = new QwtPlotRescaler(plot->canvas());
    d_rescaler->setReferenceAxis(QwtPlot::xBottom);
    d_rescaler->setAspectRatio(QwtPlot::yLeft, 1.0);
    d_rescaler->setAspectRatio(QwtPlot::yRight, 0.0);
    d_rescaler->setAspectRatio(QwtPlot::xTop, 0.0);

    for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ )
        d_rescaler->setIntervalHint(axis, QwtDoubleInterval(0.0, 1000.0));

    connect(plot, SIGNAL(resized(double, double)), 
        SLOT(showRatio(double, double)));
    return plot;
}

void MainWindow::setMouseMode(int mode)
{
    switch(mode)
    {
        case Tracking:
        {
            d_navigationInfo->setText("Tracking");
            break;
        }
        case Zooming:
        {
            d_navigationInfo->setText("Zooming");
            break;
        }
        case Panning:
        {
            d_navigationInfo->setText("Panning");
            break;
        }
    }
}

void MainWindow::setRescaleMode(int mode)
{
    bool doEnable = true;
    QString info;
    QwtDoubleRect rectOfInterest;
    QwtPlotRescaler::ExpandingDirection direction = QwtPlotRescaler::ExpandUp;

    switch(mode)
    {
        case KeepScales:
        {
            doEnable = false;
            info = "All scales remain unchanged, when the plot is resized";
            break;
        }
        case Fixed:
        {
            d_rescaler->setRescalePolicy(QwtPlotRescaler::Fixed);
            info = "The scale of the bottom axis remains unchanged, "
                "when the plot is resized. All other scales are changed, "
                "so that a pixel on screen means the same distance for" 
                "all scales.";
            break;
        }
        case Expanding:
        {
            d_rescaler->setRescalePolicy(QwtPlotRescaler::Expanding);
            info = "The scales of all axis are shrinked/expanded, when "
                "resizing the plot, keeping the distance that is represented "
                "by one pixel.";
            d_rescaleInfo->setText("Expanding");
            break;
        }
        case Fitting:
        {
            d_rescaler->setRescalePolicy(QwtPlotRescaler::Fitting);
            const QwtDoubleInterval xIntv = 
                d_rescaler->intervalHint(QwtPlot::xBottom);
            const QwtDoubleInterval yIntv = 
                d_rescaler->intervalHint(QwtPlot::yLeft);

            rectOfInterest = QwtDoubleRect( xIntv.minValue(), yIntv.minValue(),
                xIntv.width(), yIntv.width());
            direction = QwtPlotRescaler::ExpandBoth;

            info = "Fitting";
            break;
        }
    }

    d_plot->setRectOfInterest(rectOfInterest);

    d_rescaleInfo->setText(info);
    d_rescaler->setEnabled(doEnable);
    for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ )
        d_rescaler->setExpandingDirection(direction);

    if ( doEnable )
        d_rescaler->rescale();
    else
        d_plot->replot();
}

void MainWindow::showRatio(double xRatio, double yRatio)
{
	const QString msg = QString("%1, %2").arg(xRatio).arg(yRatio);
#if QT_VERSION < 0x040000
    statusBar()->message(msg);
#else
    statusBar()->showMessage(msg);
#endif
}

